package udpSve;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public abstract class AbstractNodeKomunikacija {

	private volatile boolean running = true;
	private volatile boolean stopping = false;
	protected volatile int listenPort;
	private DatagramSocket recieveSocket;

	public AbstractNodeKomunikacija(int listenPort) {
		this.listenPort = listenPort;
	}

	protected void sendPaketWithCustomHeader(InetAddress fromAddress,
			int fromPort, InetAddress sendAddress, int sendPort, int requestID,
			String komanda, String teloPoruke) {
		System.out.println("AbstractNodeKomunikacija: Saljem poruku:");
		System.out.println(sendAddress + " " + sendPort + " " + requestID + " "
				+ komanda + " " + teloPoruke);

		DatagramSocket sendSocket = null;
		DatagramPacket sendPacket;
		byte[] sendBuffer;
		try {
			sendSocket = new DatagramSocket(0, InetAddress.getLocalHost());
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		// napravi header
		// adresa|port|requesID|komanda|telo
		String request = null;
		request = fromAddress.getHostAddress() + "|" + fromPort + "|" + requestID
				+ "|" + komanda + "|" + teloPoruke;

		sendBuffer = request.getBytes();
		sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length,
				sendAddress, sendPort);
		try {
			sendSocket.send(sendPacket);
		} catch (IOException e) {
			e.printStackTrace();
		}
		sendSocket.close();
	}

	protected void sendPaket(InetAddress sendAddress, int sendPort,
			int requestID, String komanda, String teloPoruke) {
		try {
			sendPaketWithCustomHeader(InetAddress.getLocalHost(), listenPort,
					sendAddress, sendPort, requestID, komanda, teloPoruke);
		} catch (UnknownHostException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

	protected abstract void obradiPaket(InetAddress recieveAddress,
			int recievePort, int requestID, String komanda, String telo);

	protected void startRecieving() {
		running = true;
		stopping = false;
		Thread t = new Thread(new Runnable() {

			public void run() {

				recieveSocket = null;
				try {
					recieveSocket = new DatagramSocket(listenPort, InetAddress
							.getLocalHost());
				} catch (SocketException e1) {
					e1.printStackTrace();
				} catch (UnknownHostException e1) {
					e1.printStackTrace();
				}
				byte[] recieveBuffer;
				DatagramPacket recievePacket;

				System.out
						.println("AbstractNodeKomunikacija: pocinjem da slusam");

				while (running) {
					recieveBuffer = new byte[100000];// MOZDA POVECATI OVO? nveli ispada kad saljemo sve proste
					recievePacket = new DatagramPacket(recieveBuffer,
							recieveBuffer.length);
					// Udp recieve chekaj
					try {
						recieveSocket.receive(recievePacket);
						recieveSocket.setReuseAddress(true);
					} catch (SocketException e) {
						if (!stopping) {
							e.printStackTrace();
						}
						break;
					} catch (IOException e) {
						e.printStackTrace();
						continue;
					}
					// datagram packet
					String data = new String(recievePacket.getData()).trim();
					// NAPRAVITI DA BUDE ASCII ugljesa je gej
					// adresa|port|requesID|komanda|telo
					String[] split = data.split("\\|");
					InetAddress recieveAddress;
					try {
						recieveAddress = InetAddress.getByName(split[0]);
					} catch (UnknownHostException e) {
						e.printStackTrace();
						continue;
					}
					int recievePort = Integer.parseInt(split[1]);
					int requestID = Integer.parseInt(split[2]);
					String komanda = split[3];
					String telo = split[4];

					// izvuci header ko poslao id requasta komnda poruke i telo
					// poruke
					System.out
							.println("AbstractNodeKomunikacija: Primio sam poruku:");
					System.out.println(recieveAddress + " " + recievePort + " "
							+ requestID + " " + komanda + " " + telo);

					obradiPaket(recieveAddress, recievePort, requestID,
							komanda, telo);
				}
				System.out
						.println("AbstractNodeKomunikacija: prestajem da slusam");
				recieveSocket.close();
			}
		});
		t.start();

	}

	protected void stopRecieving() {
		stopping = true;
		while (recieveSocket == null) {
		}
		recieveSocket.close();
		running = false;

	}
}
